package com.study.juc.rwlock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @program: juc-study
 * @author: jzhou
 * @date: 2022-08-22 19:08
 * @version: 1.0
 * @description: 读写锁案例
 **/
public class ReentrantReadWriteLockDemo {
	public static void main(String[] args) {
		MyResource myResource  = new MyResource();
		for (int i = 1; i <=10; i++) {
			int finalI = i;
			new Thread(() -> {
				myResource.write(finalI +"", finalI +"");
			},String.valueOf(i)).start();
		}

		for (int i = 1; i <=10; i++) {
			int finalI = i;
			new Thread(() -> {
				myResource.read(finalI +"");
			},String.valueOf(i)).start();
		}

		//暂停几秒钟线程
		try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

		//读全部over才可以继续写
		for (int i = 1; i <=3; i++) {
			int finalI = i;
			new Thread(() -> {
				myResource.write(finalI +"", finalI +"");
			},"newWriteThread==="+String.valueOf(i)).start();
		}

	}
}

class MyResource{ // 资源类，模拟一个缓存
	Map<String,String> map = new HashMap<>();
	Lock lock = new ReentrantLock();
	ReadWriteLock rwl = new ReentrantReadWriteLock();

	public void write(String key,String value) {
//		lock.lock();
		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + "\t" + "正在写入");
			map.put(key,value);
			TimeUnit.MILLISECONDS.sleep(500);
			System.out.println(Thread.currentThread().getName() + "\t" + "写入完成");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
//			lock.unlock();
			rwl.writeLock().unlock();
		}
	}

	public void read(String key)  {
//		lock.lock();
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + "\t" + "正在读取");
			String s = map.get(key);
//			TimeUnit.MILLISECONDS.sleep(200);
			//暂停2s演示读锁没有结束之前，写操作不能进行
			TimeUnit.MILLISECONDS.sleep(2000);
			System.out.println(Thread.currentThread().getName() + "\t" + "完成读取" + s);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
//			lock.unlock();
			rwl.readLock().unlock();
		}
	}

}
